home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Tools & Apps / Testing & Debugging / VUAssist 1.0d10 / VUAssist Source Code / UVUAssist.inc2.p < prev    next >
Encoding:
Text File  |  1991-09-10  |  34.2 KB  |  1,183 lines  |  [TEXT/MPS ]

  1. (*+
  2.  *    File:        UVUAssist.inc2.p - MacApp 3.0b2PQR compatible version
  3.  *
  4.  *    Contains:    VU assistance methods
  5.  *
  6.  *    Written by:    David Shayer
  7.  *
  8.  *    Copyright:    © 1991 by Apple Computer, Inc., all rights reserved.
  9.  *
  10.  *  Version: 1.0d10
  11.  *
  12.  *    Change History (most recent first):
  13.  
  14.           9/10/91    JAS        indicate 3.0b2PQR compatibility, change version
  15.          8/21/91    JAS        adjust comments, change version
  16.          8/20/91    JAS        fix syntax error
  17.          8/20/91    JAS          remove debugging code
  18.          8/19/91    JAS        Revise comments, change case of GridItemSupport to
  19.                              gridItemSupport
  20.          8/15/91    JAS        Add GridItemSupport argument to IVUAssist
  21.          8/13/91    JAS        Revise comments
  22.          8/13/91    JAS        Change made in GetItemType so that kIncludeGridItems 
  23.                              will determine whether TGridItems are ever identified for use 
  24.          8/13/91    JAS        Make changes in IVUAssist since VUAssist is now a descendant
  25.                              of TEvtHandler (sets idle frequency and installs cohandler).
  26.          8/13/91    JAS        Changes in TGridItem implementation
  27.          8/13/91    JAS        Use FirstSubViewThat in place of EachSubView wherever applicable
  28.          8/6/91        JAS        Clean up change history
  29.          8/6/91        JAS        Check for GridViewItems in GetItemType only if DlogViewItems is
  30.                             true, remove TVUAssist.DoFindWindowInfo (not needed)
  31. -*)
  32.  
  33. {Historical Note:  References to the "Mole" are equivalent to references to "Agent VU".
  34. "Agent VU" was previously called the "Mole".}
  35.  
  36.  
  37. { The mole sees MacApp windows as plain windows that are empty.  MacApp
  38. doesn't put its controls in the control list, so V.U. won't even see standard
  39. Control Manager controls.  The assistance proc updates the mole buffer before
  40. it is sent back to the V.U. host, telling it that there are items in the windows, 
  41. and telling it about each item.  We tell it that the windows are dialogs, 
  42. because V.U. looks for a wider range of user interface items in dialogs.
  43.  
  44. V.U. has its own hierarchy of user interface items, based largely on the types of 
  45. interface items defined in Inside Mac which V.U. can obtain information about
  46. in non-MacApp applications.  MacApp's user interface element hierarchy is the View hierarchy.  
  47. Since the two hierarchies are not the same, VUAssist must perform a mapping between the
  48. two hierarchies.  Many of these mappings are straight-forward, but a few require some
  49. explanation.  The V.U. interface item hierarchy is as follows.  
  50.  
  51.                 |___ staticText
  52.                 |                       
  53.                 |___ editText                       
  54.                 |                                          
  55.                 |___ picture
  56. contentItem-----|
  57.                 |___ icon                       
  58.                 |                                          
  59.                 |___ userItem
  60.                 |
  61.                 |___ control-----|___ button
  62.                                   |                       
  63.                                   |___ checkBox    
  64.                                  |
  65.                                  |___ radioButton
  66.                                   |                       
  67.                                   |___ scrollBar
  68.                                  |                       
  69.                                   |___ popup
  70.                                  
  71. All V.U. interface items are considered contentItems.  Some of these contentItems are 
  72. typically found only in Dialog Manager dialogs in non-MacApp applications.  These would 
  73. be staticText, editText, picture, icon, and userItem.  Controls are Control Manager controls
  74. which may appear in any window.
  75.  
  76. The list of TView descendants which are mapped to V.U. interface items and the V.U. item
  77. to which they are mapped by V.U. by way of VUAssist is shown below.
  78.  
  79. TStaticText ---------> staticText
  80. TEditText     ---------> editText
  81. TPicture     ---------> picture
  82. TIcon         ---------> icon
  83. TButton     ---------> button
  84. TCheckbox     ---------> checkBox
  85. TRadio         ---------> radioButton
  86. TScrollBar     ---------> scrollBar
  87. TPopup         ---------> popup
  88. TTextEdit     ---------> editText
  89. (cells of TGridView -> contentItem)  - an optional feature
  90.  
  91. The last item, "cells of TGridView", deserves some explanation. TGridViews are a 
  92. problem because unlike all the other items mentioned above, where there is exactly one 
  93. MacApp object for each user interface item, there are many user interface items for a 
  94. single TGridView object.  V.U. does not yet directly support gridView types of objects.  
  95. So there is special case code for TGridViews.  Each cell in a grid is passed back as a 
  96. "CUSTOM_ITEM".  To V.U., a CUSTOM_ITEM is a user interface item which does not fall into
  97. any category more specific than contentItem.  So from a V.U. script writer's perspective,
  98. cells in TGridView objects are V.U. contentItems.
  99.  
  100. Note that the mapping of TGridView cells to contentItems is a feature which can be disabled.
  101. TVUAssist's IVUAssist method takes a boolean argument gridItemSupport.  By passing 'false'
  102. to this method, the cells of TGridViews are invisible to V.U..  You may want to do this if 
  103. your application has large gridviews or many gridviews.  In this case treating each cell as
  104. an interface item may bog down V.U. in such a way that performance is not acceptable. 
  105.  
  106. You'll also note in the code that we include TPopup descriptions in response to V.U.'s requests 
  107. for information about controls.  This is because V.U. can normally only support popups which 
  108. are implemented through the use of the popup CDEF found in System 7.0 or in the Mac Communications 
  109. Toolbox.  So V.U. expects them to be controls.}
  110.  
  111.  
  112.  
  113. {========================================== TVUAssist ================================}
  114.  
  115. {$S VUAssistSeg}
  116.  
  117. {The MoleHook is declared as type C, which means it must be an external function.
  118. The actual code for MoleHook is in assembly.  All it does is accept the call from the mole
  119. with a C interface, and then call TVUAssist.MoleAssist with a Pascal interface.}
  120. FUNCTION MoleHook (Select :integer; Input :Ptr; VAR OutputSize :integer;
  121.     Result :integer) :OSErr; C; EXTERNAL;
  122.  
  123.  
  124. { IVUAssist initializes fMoleRefNum.  fMoleRefNum contains the reference number of the 
  125. mole driver, or 0 if no mole driver has been found yet. Also initializes VUAssist as an EvtHandler, 
  126. sets idle frequency to kVUAssistIdleFreq, and installs cohandler.  Also initializes fGridItemSupport
  127. according to input argument gridItemSupport.}
  128. PROCEDURE TVUAssist.IVUAssist(gridItemSupport: boolean);
  129. BEGIN
  130.     INHERITED Initialize;
  131.     INHERITED IEventHandler(NIL);
  132.     fGridItemSupport:=gridItemSupport;
  133.     fMoleRefNum:=0;
  134.     SELF.OpenMoleDriver;
  135.     SELF.SetIdleFreq(kVUAssistIdleFreq);
  136.     gApplication.InstallCohandler(SELF, true);
  137. END;
  138.  
  139.  
  140. { Try to open the mole driver if there is one. }
  141. PROCEDURE TVUAssist.OpenMoleDriver;
  142. VAR
  143.     PBRec :ParamBlockRec;
  144.     Err :integer;
  145.     MoleName :Str15;
  146. BEGIN
  147.     MoleName:='.Mole';
  148.     PBRec.ioCompletion:=NIL;
  149.     PBRec.ioNamePtr:=@MoleName;
  150.     PBRec.ioPermssn:=fsCurPerm;
  151.     Err:=PBOpen (@PBRec, false);
  152.     IF (PBRec.ioResult=noErr) THEN
  153.     BEGIN
  154.         fMoleRefNum:=PBRec.ioRefNum;
  155.         SELF.ResumeMole;
  156.     END;
  157. END;
  158.  
  159.  
  160. { Call this routine when the application is suspended by Multifinder, to let
  161. the mole know we are no longer the frontmost app. }
  162. PROCEDURE TVUAssist.SuspendMole;
  163. BEGIN
  164.     SELF.SetDebuggerHook(NIL);
  165. END;
  166.  
  167.  
  168. { Call this routine when MultiFinder puts us back into the foreground. }
  169. PROCEDURE TVUAssist.ResumeMole; 
  170. BEGIN
  171.     SELF.SetDebuggerHook(@MoleHook);
  172. END;
  173.  
  174.  
  175.  
  176. { Tell the mole the address of our assistance procedure.}
  177. PROCEDURE TVUAssist.SetDebuggerHook (NewHook :ProcPtr); 
  178. CONST
  179.     SET_ASSIST = 100;
  180. VAR
  181.     PBRec :ParamBlockRec;
  182.     Err :integer;
  183.     LongPtr :^Longint;
  184. BEGIN
  185.     IF (fMoleRefNum<>0) THEN
  186.     BEGIN
  187.         PBRec.ioCompletion:=NIL;
  188.         PBRec.ioVRefNum:=0;
  189.         PBRec.ioRefNum:=fMoleRefNum;
  190.         PBRec.csCode:=SET_ASSIST;
  191.         LongPtr:=@PBRec.csParam[0];
  192.         LongPtr^:=LongInt(NewHook);
  193.         Err:=PBControl (@PBRec, false);
  194.         IF (PBRec.ioResult<>noErr) THEN
  195.             WriteLn ('Error sending Mole control call');
  196.     END;
  197. END;
  198.  
  199.  
  200.  
  201. { This is the routine called by MoleHook.  It dispatches out to the routines
  202. which actually assist the mole. }
  203. FUNCTION TVUAssist.MoleAssist (Select :integer; Input :Ptr; Output :Ptr; 
  204.     VAR OutputSize :integer; IntResult :integer) :integer;
  205. VAR
  206.     Result        :MoleError;
  207.     ReturnValue    :MoleError;
  208. BEGIN
  209.     Result:=MoleError(IntResult);
  210.     ReturnValue:=Result;
  211.     CASE MoleSelectors(Select) OF
  212.         SMenuInfo:
  213.             BEGIN
  214.                 ReturnValue:=SELF.DoMenuInfo (Input, Output, OutputSize, Result);
  215.             END;
  216.         SMenuItems:
  217.             BEGIN
  218.                 ReturnValue:=SELF.DoMenuItems (Input, Output, OutputSize, Result);
  219.             END;
  220.         SetMItemKey:
  221.             BEGIN
  222.             END;
  223.         SFrontWind:
  224.             BEGIN
  225.             END;
  226.         SFindWind:
  227.             BEGIN
  228.             END;
  229.         SWindInfo:
  230.             BEGIN
  231.                 ReturnValue:=SELF.DoSendWindowInfo (Input, Output, OutputSize, Result);
  232.             END;
  233.         SFindCtl:
  234.             BEGIN
  235.                 ReturnValue:=SELF.DoFindControl (Input, Output, OutputSize, Result);
  236.             END;
  237.         SCtlInfo:
  238.             BEGIN
  239.                 ReturnValue:=SELF.DoSendControlInfo (Input, Output, OutputSize, Result);
  240.             END;
  241.         SFindDItem:
  242.             BEGIN
  243.             END;
  244.         SDItemInfo:
  245.             BEGIN
  246.                 ReturnValue:=SELF.DoSendDlogItemInfo (Input, Output, OutputSize, Result);
  247.             END;
  248.         OTHERWISE
  249.             BEGIN
  250.             END;
  251.     END; {case} 
  252.     MoleAssist:=integer(ReturnValue);
  253. END;
  254.  
  255.  
  256. {------------------------------------------------------------------------------------}
  257. { the routines for handling individual mole requests.  Each routine handles
  258.   exactly one mole request. }
  259.  
  260. { Handle a request for specific menu items.  The Mole can get info on menus in the
  261. menu bar, but we have to supply info on popup menus. }
  262. FUNCTION TVUAssist.DoMenuItems (Input :Ptr; Output :Ptr; VAR OutputSize :integer; 
  263.     Result :MoleError) :MoleError;
  264. VAR
  265.     MenuReqPtr        :SendMenuItemsParamsPtr;
  266.     MenuDescPtr        :MoleDataBlockPtr;
  267.     Popup            :TPopup;
  268. BEGIN
  269.     DoMenuItems:=Result; {initially, inherit result from mole}
  270.     MenuReqPtr:=SendMenuItemsParamsPtr(Input);
  271.     MenuDescPtr:=MoleDataBlockPtr(Output);
  272.     
  273.     { We don't need to respond when V.U. wants to find menus by rank (indicated by a menu_ID of 0).  
  274.     We do need to supply information about popups when the specified ID is non-zero. }
  275.     IF MenuReqPtr^.menu_ID<>0 THEN
  276.     BEGIN { find menu by menu ID }
  277.         IF (Result<>mNoErr) THEN
  278.         BEGIN
  279.             Popup:=SELF.MenuIDToPopup (MenuReqPtr^.menu_ID);
  280.             IF Popup<>NIL THEN
  281.             BEGIN
  282.                 DoMenuItems:=SELF.FillPopupItemDesc (Popup, RANK_OF_THE_INVISIBLE, 
  283.                     MenuReqPtr^.start_item, MenuReqPtr^.stop_item, MenuDescPtr, OutputSize);
  284.             END;
  285.         END;
  286.     END;
  287. END;
  288.  
  289.  
  290. { Handle a request for menu info.  The Mole can get info on menus in the
  291. menu bar, but we have to supply info on popup menus. }
  292. FUNCTION TVUAssist.DoMenuInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer; 
  293.     Result :MoleError) :MoleError;
  294. VAR
  295.     MenuReqPtr        :SendMenuInfoParamsPtr;
  296.     MenuDescPtr        :MoleMenuInfoPtr;
  297.     Popup            :TPopup;
  298. BEGIN
  299.     DoMenuInfo:=Result; {initially, inherit result from mole}
  300.     MenuReqPtr:=SendMenuInfoParamsPtr(Input);
  301.     MenuDescPtr:=MoleMenuInfoPtr(Output);
  302.     
  303.     { We don't need to respond when V.U. wants to find menus by rank (indicated by a menu_ID of 0).  
  304.     We do need to supply information about popups when the specified ID is non-zero. }
  305.     IF MenuReqPtr^.menu_ID<>0 THEN
  306.     BEGIN { find menu by menu ID }
  307.         IF (Result<>mNoErr) THEN
  308.         BEGIN
  309.             Popup:=SELF.MenuIDToPopup (MenuReqPtr^.menu_ID);
  310.             IF Popup<>NIL THEN
  311.             BEGIN
  312.                 SELF.FillPopupDesc (Popup, RANK_OF_THE_INVISIBLE, MenuDescPtr, OutputSize);
  313.                 DoMenuInfo:=mNoErr;
  314.             END;
  315.         END;
  316.     END;
  317. END;
  318.  
  319.  
  320.  
  321. { Revise the values of the controlCount and numItems fields of the MoleWDescPtr, given
  322. knowledge of MacApp views. Also update validFlags and windowKind fields. WindowKind is set 
  323. to dialogKind so that V.U. will look for things that it can normally only see in dialogs 
  324. (such as icons and pictures) }
  325. FUNCTION TVUAssist.DoSendWindowInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  326.     Result :MoleError) :MoleError;
  327. VAR
  328.     WindReqPtr    :DWindReqPtr;
  329.     WindDescPtr    :MoleWDescPtr;
  330.     Window        :TWindow;
  331. BEGIN
  332.     DoSendWindowInfo:=Result; {initially, inherit result from mole}
  333.     WindReqPtr:=DWindReqPtr(Input);
  334.     WindDescPtr:=MoleWDescPtr(Output);
  335.     Window:=SELF.RankToWindow (WindReqPtr^);
  336.     IF Window<>NIL THEN 
  337.     BEGIN
  338.         WindDescPtr^.validFlags := BOR (WindDescPtr^.validFlags, VCTLCNT_MASK);
  339.         WindDescPtr^.validFlags := BOR (WindDescPtr^.validFlags, VITEMCNT_MASK);
  340.         WindDescPtr^.windowKind:=dialogKind;
  341.         WindDescPtr^.controlCount:=SELF.ViewCount (Window, false);
  342.         WindDescPtr^.numItems:=SELF.ViewCount (Window, true);
  343.         { OutputSize is filled in by the mole }
  344.         DoSendWindowInfo:=mNoErr;
  345.     END;
  346. END;
  347.  
  348.  
  349. { The mole sends us a point location in global coordinates.  We need to figure out
  350. which window and which control that point is in (if any), and send back info about
  351. that control. V.U. utilizes this routine for Control Manager controls (TCtlMgr) only.}
  352. FUNCTION TVUAssist.DoFindControl (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  353.     Result :MoleError) :MoleError;
  354. VAR
  355.     CtrlReqPtr    :SendFindControlParamPtr;
  356.     CtrlDescPtr    :MoleCDescPtr;
  357.     TargetPoint    :SendFindControlParam;
  358.     part        :integer;
  359.     wind        :WindowPeek;
  360.     SavePort    :GrafPtr;
  361.     Control        :TCtlMgr;
  362.     Rank        :integer;
  363.     SaveCtlList    :ControlHandle;
  364.     WhichCtl    :ControlHandle;
  365.     Window        :TWindow;
  366.     VPt            :VPoint;
  367. BEGIN
  368.     DoFindControl:=Result; {initially, inherit result from mole}
  369.     CtrlReqPtr:=SendFindControlParamPtr(Input);
  370.     TargetPoint:=CtrlReqPtr^;
  371.     CtrlDescPtr:=MoleCDescPtr(Output);
  372.  
  373.     part:=FindWindow (TargetPoint, WindowPtr(wind));
  374.     { The mole also tests for part=inSysWindow, but we'll let the mole handle those cases}
  375.     IF (wind<>NIL) AND (part=inContent) THEN
  376.     BEGIN
  377.         Window:=gApplication.WMgrToWindow(WindowPtr(wind));
  378.         IF (Window<>NIL) THEN
  379.         BEGIN
  380.             Control:=SELF.PointToControl (Window, TargetPoint, Rank);
  381.             IF Control<>NIL THEN
  382.             BEGIN
  383.                 part:=-1;
  384.                 { Get the control part code.  Controls are not kept in the controllist,
  385.                 so we temporarily put them in there.  Also, they are in their subviews
  386.                 local coordinate system, so we must convert targetpoint. }
  387.                 GetPort (SavePort);
  388.                 SetPort (WindowPtr(wind));
  389.                 IF Window.Focus THEN
  390.                 BEGIN
  391.                     SaveCtlList:=wind^.controlList;
  392.                     wind^.controlList:=Control.fCMgrControl;
  393.                     SELF.GlobalToWindow (Window, TargetPoint, VPt);
  394.                     SELF.WindowToView (Control, VPt, TargetPoint);
  395.                     part:=FindControl (TargetPoint, WindowPtr(wind), WhichCtl);
  396.                     wind^.controlList:=SaveCtlList;
  397.                 END;
  398.                 SetPort (SavePort);
  399.                 
  400.                 IF (SELF.FillCtrlDesc (CtrlDescPtr, part, SELF.WindowToRank(wind), 
  401.                     Rank, Control, OutputSize)) THEN
  402.                 BEGIN
  403.                     DoFindControl:=mNoErr;
  404.                 END;
  405.             END;
  406.         END;
  407.     END;
  408. END;
  409.  
  410.  
  411. { Read the input parameter to see which control V.U. wants info on, then
  412. fill in the SendCtlInfoParamsPtr record.  The mole can't gather any info about
  413. MacApp controls without our help, so we fill in the whole record, except for part, 
  414. which doesn't apply.}
  415. FUNCTION TVUAssist.DoSendControlInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  416.     Result :MoleError) :MoleError;
  417. VAR
  418.     CtrlReqPtr    :SendCtlInfoParamsPtr;
  419.     CtrlDescPtr    :MoleCDescPtr;
  420.     Window        :TWindow;
  421.     Control        :TControl;
  422.     gridItem    :TGridItem;
  423. BEGIN
  424.     DoSendControlInfo:=Result; {initially, inherit result from mole}
  425.     gridItem:=NIL;
  426.     CtrlReqPtr:=SendCtlInfoParamsPtr(Input);
  427.     CtrlDescPtr:=MoleCDescPtr(Output);
  428.  
  429.     Window:=SELF.RankToWindow (CtrlReqPtr^.window_rank);
  430.     IF Window<>NIL THEN
  431.     BEGIN
  432.         Control:=TControl(SELF.RankToItem (Window, CtrlReqPtr^.control_rank, false, gridItem));
  433.         IF Control<>NIL THEN
  434.         BEGIN
  435.             IF (SELF.FillCtrlDesc (CtrlDescPtr, -1, CtrlReqPtr^.window_rank, 
  436.                 CtrlReqPtr^.control_rank, Control, OutputSize)) THEN
  437.             BEGIN
  438.                 DoSendControlInfo:=mNoErr;
  439.             END;
  440.         END;
  441.     END;
  442. END;
  443.  
  444.  
  445. { Read the input to see which dialog item in which window V.U. wants data on, and
  446. fill in the dialogiteminfo record. }
  447. FUNCTION TVUAssist.DoSendDlogItemInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
  448.     Result :MoleError) :MoleError;
  449. VAR
  450.     DlogReqPtr    :SendDItemInfoPtr;
  451.     DlogDescPtr    :MoleDItemInfoPtr;
  452.     Window        :TWindow;
  453.     View        :TView;
  454.     gridItem    :TGridItem;
  455. BEGIN
  456.     DoSendDlogItemInfo:=Result; {initially, inherit result from mole}
  457.     gridItem:=NIL;
  458.     DlogReqPtr:=SendDItemInfoPtr(Input);
  459.     DlogDescPtr:=MoleDItemInfoPtr(Output);
  460.     
  461.     Window:=SELF.RankToWindow (DlogReqPtr^.window_rank);
  462.     IF Window<>NIL THEN
  463.     BEGIN
  464.         View:=SELF.RankToItem (Window, DlogReqPtr^.item_num, true, gridItem);
  465.         IF View<>NIL THEN
  466.         BEGIN
  467.             SELF.FillDlogItemDesc (DlogDescPtr, Window, DlogReqPtr^.window_rank, 
  468.                 DlogReqPtr^.item_num, View, OutputSize, gridItem);
  469.             DoSendDlogItemInfo:=mNoErr;
  470.         END;
  471.     END;
  472. END;
  473.  
  474.  
  475. {------------------------------------------------------------------------------------}
  476. { routines for filling in mole data structures }
  477.  
  478. { Given a TPopup object, fill in the mole's menu descriptor record. }
  479. PROCEDURE TVUAssist.FillPopupDesc (Popup: TPopup; MenuRank: integer; 
  480.     MenuDescPtr :MoleMenuInfoPtr; VAR OutputSize :integer);
  481. VAR
  482.     TheMenuHdl    :MenuHandle;
  483. BEGIN
  484.     TheMenuHdl := Popup.GetMenuHandle;
  485.     WITH MenuDescPtr^ DO
  486.     BEGIN
  487.         num_items:=CountMItems (TheMenuHdl);
  488.         rank:=MenuRank;
  489.         left_edge:=0;
  490.         menuID:=Popup.GetMenuID;
  491.         menuWidth:=TheMenuHdl^^.menuWidth;
  492.         menuHeight:=TheMenuHdl^^.menuHeight;
  493.         enableFlags:=TheMenuHdl^^.enableFlags;
  494.         text_name:=TheMenuHdl^^.menuData;
  495.         
  496.         { this ugly thing computes the length (bytes used) of MoleMenuInfo }
  497.         OutputSize:=sizeof(MoleMenuInfo) - (255-length(text_name));
  498.     END;
  499. END;
  500.  
  501.  
  502. { Given a TPopup object, fill in the mole's menuitem descriptor record. }
  503. FUNCTION TVUAssist.FillPopupItemDesc (Popup: TPopup; MenuRank: integer; start: integer; 
  504.     stop: integer; MenuItemDescPtr :MoleDataBlockPtr; VAR OutputSize :integer) :MoleError;
  505.     
  506.     { this function depends upon Ptr being a pointer to a single byte }
  507.     FUNCTION SeekMenuItem (ItemNum: integer; MenuHdl: MenuHandle) :Ptr;
  508.     VAR
  509.         SeekPtr    :Ptr;
  510.         SeekNum    :integer;
  511.     BEGIN
  512.         SeekNum:=1;
  513.         SeekPtr:= Ptr(ORD4(@MenuHdl^^.menuData) + length(MenuHdl^^.menuData) + 1);
  514.         WHILE (SeekNum<ItemNum) AND (SeekPtr^<>0) DO
  515.         BEGIN
  516.             SeekPtr:= Ptr(ORD4(SeekPtr) + SeekPtr^ + ADDITIONAL_MENU_ITEM_DATA);
  517.             SeekNum:=SeekNum+1;
  518.         END;
  519.         SeekMenuItem:=SeekPtr;
  520.     END;
  521.     
  522. VAR
  523.     StartPtr    :Ptr;
  524.     StopPtr        :Ptr;VAR
  525.     TheMenuHdl    :MenuHandle;
  526. BEGIN
  527.     
  528.     TheMenuHdl := Popup.GetMenuHandle;
  529.     
  530.     FillPopupItemDesc:=mNoErr;
  531.     IF (start>CountMItems (TheMenuHdl)) OR (start<1) THEN
  532.     BEGIN
  533.         FillPopupItemDesc:=mBadMenuItemIndex;
  534.         EXIT (FillPopupItemDesc);
  535.     END;
  536.     
  537.     IF stop>CountMItems (TheMenuHdl) THEN
  538.     BEGIN
  539.         stop:=CountMItems (TheMenuHdl);
  540.         FillPopupItemDesc:=mBadLastMenuItemIndex;
  541.     END;
  542.     
  543.     StartPtr:=SeekMenuItem (start, TheMenuHdl);
  544.     StopPtr:=SeekMenuItem (stop+1, TheMenuHdl);
  545.     IF (StartPtr=NIL) OR (StopPtr=NIL) THEN
  546.     BEGIN
  547.         FillPopupItemDesc:=mBadMenuItemIndex;
  548.         EXIT (FillPopupItemDesc);
  549.     END;
  550.     MenuItemDescPtr^.blockLength:=stop-start+1;
  551.     BlockMove (StartPtr, @MenuItemDescPtr^.dataBlock[0], ORD4(StopPtr)-ORD4(StartPtr));
  552.     
  553.     { this ugly thing computes the length (bytes used) of MoleDataBlock }
  554.     OutputSize:=sizeof(integer) + (ORD4(StopPtr)-ORD4(StartPtr));
  555. END;
  556.  
  557.  
  558. { Fill in a mole control descriptor record.  Valid descendants of TControl are descendants of
  559. TCtlMgr and TPopup. Will return false if TControl is not a descendant of TCtlMgr or TPopup.}
  560. FUNCTION TVUAssist.FillCtrlDesc (CtrlDescPtr :MoleCDescPtr; thePart :integer; 
  561.     WindRank :integer; ControlRank :integer; Control :TControl; VAR OutputSize :integer): BOOLEAN;
  562. VAR
  563.     dummy        :longint;
  564.     ControlHdl    :ControlHandle;
  565.     aVRect        :VRect;
  566.     TheMenuHdl    :MenuHandle;
  567. BEGIN
  568.     FillCtrlDesc:=FALSE; 
  569.     IF Member (Control, TPopup) THEN
  570.     BEGIN
  571.         TheMenuHdl := TPopup(Control).GetMenuHandle;
  572.         WITH CtrlDescPtr^ DO
  573.         BEGIN
  574.             validFlags:=VALL_C_MASK;
  575.             IF thePart=-1 THEN
  576.             BEGIN
  577.                 dummy:=validFlags;
  578.                 BClr (dummy, VCPART);
  579.                 validFlags:=dummy;
  580.             END;
  581.             owner_rank:=WindRank;
  582.             Control.GetExtent (aVRect);
  583.             VRectToRect(aVRect, ctlRect);
  584.             SELF.ViewRectToWindowRect (ctlRect, Control);
  585.  
  586.             ctlValue:=TPopup(Control).GetCurrentItem;
  587.             ctlMin:=1;
  588.             ctlMax:=CountMItems(TheMenuHdl);
  589.             ctlHilite:=0;
  590.             IF thePart=-1 THEN
  591.                 part:=0
  592.             ELSE
  593.                 part:=thePart;
  594.             ctlRank:=ControlRank;
  595.             ctlDefID:=POPUP_CDEF*16;
  596.             popupMenuID:=TPopup(Control).GetMenuID;
  597.             text_name:=TheMenuHdl^^.menuData;
  598.     
  599.             { this ugly thing computes the length (bytes used) of CtrlDescPtr }
  600.             OutputSize:=sizeof(MoleControlDescriptor) - (255-length(text_name));
  601.         END;
  602.     END
  603.     ELSE IF Member (Control, TCtlMgr) THEN {non-popup member of TCtlMgr}
  604.     BEGIN
  605.         ControlHdl:=TCtlMgr(Control).fCMgrControl;
  606.         WITH CtrlDescPtr^, ControlHdl^^ DO
  607.         BEGIN
  608.             validFlags:=VALL_C_MASK;
  609.             IF thePart=-1 THEN
  610.             BEGIN
  611.                 dummy:=validFlags;
  612.                 BClr (dummy, VCPART);
  613.                 validFlags:=dummy;
  614.             END;
  615.             owner_rank:=WindRank;
  616.             ctlRect:=contrlRect;
  617.             SELF.ViewRectToWindowRect (ctlRect, Control);
  618.             ctlValue:=contrlValue;
  619.             ctlMin:=contrlMin;
  620.             ctlMax:=contrlMax;
  621.             ctlHilite:=contrlHilite;
  622.             IF thePart=-1 THEN
  623.                 part:=0
  624.             ELSE
  625.                 part:=thePart;
  626.             ctlRank:=ControlRank;
  627.             ctlDefID:=BAND(BSR(longint(contrlDefProc), 24), $7);
  628.             IF Member (Control, TScrollBar) THEN
  629.                 ctlDefID:=ctlDefID+16;
  630.             popupMenuID:=0;
  631.             text_name:=contrlTitle;
  632.     
  633.             { this ugly thing computes the length (bytes used) of CtrlDescPtr }
  634.             OutputSize:=sizeof(MoleControlDescriptor) - (255-length(text_name));
  635.             FillCtrlDesc:=TRUE;
  636.         END;
  637.     END;
  638. END;
  639.  
  640.  
  641. PROCEDURE TVUAssist.ViewRectToWindowRect (VAR aRect :Rect; aView :TView);
  642. VAR
  643.     VPt :VPoint;
  644. BEGIN
  645.     PtToVPt(aRect.topLeft, VPt);
  646.     aView.LocalToWindow (VPt);
  647.     aRect.topLeft:=VPtToPt (VPt);
  648.     PtToVPt(aRect.botRight, VPt);
  649.     aView.LocalToWindow (VPt);
  650.     aRect.botRight:=VPtToPt (VPt);
  651. END;
  652.  
  653.  
  654. { Fill in a mole dialog item descriptor record }
  655. PROCEDURE TVUAssist.FillDlogItemDesc (DlogDescPtr :MoleDItemInfoPtr; Window :TWindow;
  656.     WindRank :integer; ItemRank :integer; Item :TView; VAR OutputSize :integer; gridItem :TGridItem);
  657. VAR
  658.     aVRect        :VRect;
  659.     TextLen     :longint;
  660.     TextHdl     :Handle;
  661.     ItemKind    :ViewItems;
  662.     aCell        :GridCell;
  663.     VBox        :VRect;        
  664. BEGIN
  665.     WITH DlogDescPtr^ DO
  666.     BEGIN
  667.         ItemKind:=SELF.GetItemType (Item, true, true);
  668.         { fill in box, itemType, item_enabled, has_text and text_name here }
  669.         CASE ItemKind OF
  670.             VINotMember:
  671.                 ;
  672.             VIButton:
  673.             BEGIN
  674.                 TCtlMgr(Item).ControlArea (VBox);
  675.                 VRectToRect(VBox, box);
  676.                 itemType:=btnCtrlItem;
  677.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
  678.                 has_text:=TRUE;
  679.                 TCtlMgr(Item).GetText (text_name);
  680.             END;
  681.             VIRadio:
  682.             BEGIN
  683.                 TCtlMgr(Item).ControlArea (VBox);
  684.                 VRectToRect(VBox, box);
  685.                 itemType:=radCtrlItem;
  686.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
  687.                 has_text:=TRUE;
  688.                 TCtlMgr(Item).GetText (text_name);
  689.             END;
  690.             VICheckBox:
  691.             BEGIN
  692.                 TCtlMgr(Item).ControlArea (VBox);
  693.                 VRectToRect(VBox, box);
  694.                 itemType:=chkCtrlItem;
  695.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
  696.                 has_text:=TRUE;
  697.                 TCtlMgr(Item).GetText (text_name);
  698.             END;
  699.             VIScrollBar:
  700.             BEGIN
  701.                 TCtlMgr(Item).ControlArea (VBox);
  702.                 VRectToRect(VBox, box);
  703.                 itemType:=resCtrlItem;
  704.                 item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
  705.                 has_text:=TRUE;
  706.                 TCtlMgr(Item).GetText (text_name);
  707.             END;
  708.             VIStatText:
  709.             BEGIN
  710.                 Item.GetExtent (aVRect);
  711.                 VRectToRect(aVRect, box);
  712.                 itemType:=statText;
  713.                 item_enabled:=FALSE;
  714.                 has_text:=TRUE;
  715.                 TStaticText(Item).GetText (text_name);
  716.             END;
  717.             VIEditText:
  718.             BEGIN
  719.                 Item.GetExtent (aVRect);
  720.                 VRectToRect(aVRect, box);
  721.                 itemType:=editText;
  722.                 item_enabled:=Item.IsActive;
  723.                 has_text:=TRUE;
  724.                 TStaticText(Item).GetText (text_name);
  725.             END;
  726.             VIIcon:
  727.             BEGIN
  728.                 Item.GetExtent (aVRect);
  729.                 VRectToRect(aVRect, box);
  730.                 itemType:=iconItem;
  731.                 item_enabled:=Item.IsActive;
  732.                 has_text:=FALSE;
  733.                 item_text_ptr:=NIL;
  734.             END;
  735.             VIPopup:
  736.             BEGIN
  737.                 Item.GetExtent (aVRect);
  738.                 VRectToRect(aVRect, box);
  739.                 itemType:=resCtrlItem;
  740.                 item_enabled:=Item.IsActive;
  741.                 has_text:=FALSE;
  742.                 item_text_ptr:=NIL;
  743.             END;
  744.             VIPicture:
  745.             BEGIN
  746.                 Item.GetExtent (aVRect);
  747.                 VRectToRect(aVRect, box);
  748.                 itemType:=picItem;
  749.                 item_enabled:=Item.IsActive;
  750.                 has_text:=FALSE;
  751.                 item_text_ptr:=NIL;
  752.             END;
  753.             VITextEdit:
  754.             BEGIN
  755.                 Item.GetExtent (aVRect);
  756.                 VRectToRect(aVRect, box);
  757.                 itemType:=editText;
  758.                 item_enabled:=Item.IsActive;
  759.                 has_text:=TRUE;
  760.                 TextHdl:=TTEView(Item).ExtractText;
  761.                 TextLen:=GetHandleSize (TextHdl);
  762.                 IF TextLen>255 THEN TextLen:=255;
  763.                 BlockMove (TextHdl^, @text_name, TextLen);
  764.             END;
  765.             VIGridItem:
  766.             BEGIN
  767.                 gridItem.GetExtent (aVRect);
  768.                 VRectToRect(aVRect, box);
  769.                 itemType:=CUSTOM_ITEM;
  770.                 item_enabled:=gridItem.fGridView.IsActive;
  771.                 IF Member (Item, TTextGridView) THEN
  772.                 BEGIN  {item has text associated with it}
  773.                     has_text:=TRUE;
  774.                     aCell.v:=gridItem.fRow;
  775.                     aCell.h:=gridItem.fColumn;
  776.                     TTextGridView(gridItem.fGridView).GetText (aCell, text_name);
  777.                 END
  778.                 ELSE   {item may not have text associated with it}
  779.                 BEGIN
  780.                     has_text:=FALSE;
  781.                     item_text_ptr:=NIL;
  782.                 END;
  783.             END;
  784.         END; { case }
  785.         SELF.ViewRectToWindowRect (box, Item);
  786.         { fill in ctlRank, owner_rank, and item_num here }
  787.         ctlRank:=SELF.ItemToRank (Window, Item, false);
  788.         owner_rank:=WindRank;
  789.         item_num:=ItemRank;
  790.             
  791.         { this ugly thing computes the length (bytes used) of MoleDItemInfo }
  792.         IF ItemKind<>VINotMember THEN
  793.             OutputSize:=sizeof(MoleDItemInfo) - (255-length(text_name));
  794.         
  795.         IF gridItem <> NIL THEN
  796.             gridItem.Free;
  797.     END; { with }
  798. END;
  799.  
  800.  
  801. {------------------------------------------------------------------------------------}
  802. { routines for searching through the view tree to find particular views }
  803.  
  804. { Given the rank (z-order) of a window, return the window object.  Invisible
  805. windows are not considered to be in the window list, for ranking purposes. }
  806. FUNCTION TVUAssist.RankToWindow (Rank :integer) :TWindow;
  807. VAR
  808.     i: integer;
  809.     Window :WindowPeek;
  810. BEGIN
  811.     RankToWindow:=NIL;
  812.     i:=1;
  813.     Window:=WindowPeek(FrontWindow);
  814.     WHILE Window<>NIL DO
  815.     BEGIN
  816.         IF Window^.visible THEN
  817.         BEGIN
  818.             IF i=Rank THEN
  819.             BEGIN
  820.                 RankToWindow:=gApplication.WMgrToWindow(WindowPtr(Window));
  821.                 LEAVE;
  822.             END;
  823.             i:=i+1;
  824.         END;
  825.         Window:=Window^.nextWindow;
  826.     END;
  827. END;
  828.  
  829.  
  830. {Given a window ptr, return the window's rank (z-order).}
  831. FUNCTION TVUAssist.WindowToRank (WindToFind :WindowPeek) :integer;
  832. VAR
  833.     i: integer;
  834.     Window :WindowPeek;
  835. BEGIN
  836.     WindowToRank:=0;
  837.     i:=1;
  838.     Window:=WindowPeek(FrontWindow);
  839.     WHILE Window<>NIL DO
  840.     BEGIN
  841.         IF Window^.visible THEN
  842.         BEGIN
  843.             IF WindToFind=Window THEN
  844.             BEGIN
  845.                 WindowToRank:=i;
  846.                 LEAVE;
  847.             END;
  848.             i:=i+1;
  849.         END;
  850.         Window:=Window^.nextWindow;
  851.     END;
  852. END;
  853.  
  854.  
  855. { Convert a point in global coordinates to window coordinates. }
  856. PROCEDURE TVUAssist.GlobalToWindow (Window :TWindow; Pt :Point; VAR VPt :VPoint);
  857. VAR
  858.     SavePort    :GrafPtr;
  859.     TargetPoint    :Point;
  860. BEGIN
  861.     VPt.h:=0;
  862.     VPt.v:=0;
  863.     GetPort (SavePort);
  864.     SetPort (Window.GetGrafPort);
  865.     IF Window.Focus THEN
  866.     BEGIN
  867.         TargetPoint:=Pt;
  868.         GlobalToLocal (TargetPoint);
  869.         Window.QDToViewPt(TargetPoint, VPt);
  870.     END;
  871.     SetPort (SavePort);
  872. END;
  873.  
  874.  
  875. { Convert a point in window coordinates to a subview's coordinates. Return both a
  876. VPoint and a QDPoint. }
  877. PROCEDURE TVUAssist.WindowToView (View :TView; VAR VPt :VPoint; VAR Pt :Point);
  878. BEGIN
  879.     Pt.h:=0;
  880.     Pt.v:=0;
  881.     View.WindowToLocal(VPt);
  882.     IF View.Focus THEN
  883.         Pt:=View.ViewToQDPt (VPt);
  884. END;
  885.  
  886.  
  887.  
  888. { In the front (active) window, given the menu ID of a popup item, return the  
  889. popup menu object and its rank. }
  890. FUNCTION TVUAssist.MenuIDToPopup (MenuID :integer) :TPopup;
  891. VAR
  892.     foundView     :TView;
  893.     dummyView    :TView;
  894.     window        :TWindow;
  895.     
  896.     FUNCTION TestSubID(theSubView: TView): BOOLEAN;
  897.     BEGIN
  898.         IF theSubView.IsShown THEN
  899.         BEGIN    
  900.             IF SELF.GetItemType (theSubView, false, false)=VIPopup THEN
  901.             BEGIN
  902.                 IF TPopup(theSubView).fMenuID=MenuID THEN
  903.                     foundView:=theSubView;
  904.             END;
  905.             IF (foundView=NIL) THEN
  906.                 dummyView:=theSubView.FirstSubViewThat (TestSubID);
  907.         END;
  908.         TestSubID:=foundView <> NIL;
  909.     END;
  910.     
  911. BEGIN
  912.     foundView:=NIL;
  913.     window:=gApplication.GetActiveWindow;
  914.     IF (Window<>NIL) & (Window.IsShown) THEN
  915.         dummyView:=Window.FirstSubViewThat (TestSubID);
  916.     MenuIDToPopup:=TPopup(foundView);
  917. END;
  918.  
  919.  
  920. { Given a window object and a point in global coordinates,
  921. find the control which is under that point. Only descendants of
  922. TCtlMgr are considered.}
  923. FUNCTION TVUAssist.PointToControl (Window :TWindow; Pt :Point; VAR Rank :integer) :TCtlMgr;
  924. VAR
  925.     foundView     : TView;
  926.     dummyView    : TView;
  927.     VPt            : VPoint;
  928.     TestPoint    : VPoint;
  929.     DummyPoint    : Point;
  930.     aRect        : Rect;
  931.     
  932.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  933.     VAR
  934.         ItemType :ViewItems;
  935.     BEGIN
  936.         IF theSubView.IsShown THEN
  937.         BEGIN    
  938.             IF Member (theSubView, TCtlMgr) THEN
  939.             BEGIN
  940.                 TestPoint:=VPt;
  941.                 SELF.WindowToView (theSubView, TestPoint, DummyPoint);
  942.                 IF theSubView.ContainsMouse(TestPoint) THEN
  943.                     foundView:=theSubView;
  944.             END;
  945.             IF (foundView=NIL) THEN
  946.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  947.         END;
  948.         TestSubView:=foundView <> NIL;
  949.     END;
  950.     
  951. BEGIN
  952.     foundView:=NIL;
  953.     SELF.GlobalToWindow (Window, Pt, VPt);
  954.     IF Window.IsShown THEN
  955.         dummyView:=Window.FirstSubViewThat (TestSubView);
  956.     Rank:=SELF.ItemToRank (Window, foundView, false);
  957.     PointToControl:=TCtlMgr(foundView);
  958. END;
  959.  
  960.  
  961. { Walk the view hierarchy tree, counting the number of user interface items.
  962. Only visible views and items are counted. }
  963. FUNCTION TVUAssist.ViewCount (Window :TWindow; DlogViewItems :Boolean) :integer;
  964. VAR
  965.     ItemCount :integer;
  966.     
  967.     PROCEDURE DoToSubView(theSubView: TView);
  968.     VAR
  969.         ItemType: ViewItems;
  970.     BEGIN
  971.         IF theSubView.IsShown THEN
  972.         BEGIN
  973.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  974.             IF ItemType<>VINotMember THEN
  975.             BEGIN
  976.                 IF ItemType=VIGridItem THEN
  977.                     ItemCount:=ItemCount+SELF.CountGridItems (TGridView(theSubView))
  978.                 ELSE
  979.                     ItemCount := ItemCount + 1;
  980.             END;
  981.             IF Member (theSubView, TView) THEN
  982.                 theSubView.EachSubView (DoToSubView);
  983.         END;
  984.     END;
  985.     
  986. BEGIN
  987.     ItemCount:=0;
  988.     IF Window.IsShown THEN
  989.         Window.EachSubView (DoToSubView);
  990.     ViewCount:=ItemCount;
  991. END;
  992.  
  993.  
  994. {Given a control or dialog item (View), and the window its in (Window), return its rank. }
  995. FUNCTION TVUAssist.ItemToRank (Window :TWindow; View :TView; DlogViewItems :Boolean) :integer;
  996. VAR
  997.     ItemCount    :integer;
  998.     Rank         :integer;
  999.     dummyView    :TView;
  1000.     
  1001.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  1002.     VAR
  1003.         ItemType:    ViewItems;
  1004.     BEGIN
  1005.         IF theSubView.IsShown THEN
  1006.         BEGIN    
  1007.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  1008.             IF ItemType<>VINotMember THEN
  1009.             BEGIN
  1010.                 IF ItemType=VIGridItem THEN
  1011.                 BEGIN
  1012.                     IF (Member(View, TGridItem)) & (theSubView=TGridItem(View).fGridView) THEN
  1013.                         Rank:=ItemCount+TGridItem(View).fRank
  1014.                     ELSE
  1015.                         ItemCount:=ItemCount+SELF.CountGridItems (TGridView(theSubView));
  1016.                 END
  1017.                 ELSE BEGIN
  1018.                     ItemCount := ItemCount + 1;
  1019.                     IF theSubView=View THEN
  1020.                         Rank:=ItemCount;
  1021.                 END;
  1022.             END;
  1023.             IF (Rank=0) THEN
  1024.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  1025.         END;
  1026.         TestSubView:=Rank <> 0;
  1027.     END;
  1028.     
  1029. BEGIN
  1030.     Rank:=0;    
  1031.     ItemCount:=0;
  1032.     IF Window.IsShown THEN
  1033.         dummyView:=Window.FirstSubViewThat (TestSubView);
  1034.     ItemToRank:=Rank;
  1035. END;
  1036.  
  1037.  
  1038. { Given a window object and the rank (z-order) of an item, return the item object. If
  1039. the item is a cell of a TGridView object, return that object in gridItem.}
  1040. FUNCTION TVUAssist.RankToItem (Window :TWindow; Rank :integer; DlogViewItems :Boolean;
  1041.                                VAR gridItem: TGridItem) :TView;
  1042. VAR
  1043.     ItemCount    :integer;
  1044.     foundView     :TView;
  1045.     dummyView    :TView;
  1046.     
  1047.     FUNCTION TestSubView(theSubView: TView): BOOLEAN;
  1048.     VAR
  1049.         ItemType:    ViewItems;
  1050.         GridCount:    integer;
  1051.     BEGIN
  1052.         IF theSubView.IsShown THEN
  1053.         BEGIN    
  1054.             ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
  1055.             IF ItemType<>VINotMember THEN
  1056.             BEGIN
  1057.                 IF (ItemType=VIGridItem) THEN
  1058.                 BEGIN
  1059.                     GridCount:=SELF.CountGridItems (TGridView(theSubView));
  1060.                     IF (Rank>ItemCount) AND (Rank<=ItemCount+GridCount) THEN
  1061.                     BEGIN
  1062.                         New (gridItem);
  1063.                         FailNil (gridItem);
  1064.                         gridItem.IGridItem (TGridView(theSubView), Rank-ItemCount);
  1065.                         foundView:=theSubView;
  1066.                     END;
  1067.                     ItemCount := ItemCount + GridCount;
  1068.                 END
  1069.                 ELSE BEGIN
  1070.                     ItemCount := ItemCount + 1;
  1071.                     IF ItemCount=Rank THEN
  1072.                         foundView:=theSubView;
  1073.                 END;
  1074.             END;
  1075.             IF (foundView=NIL) THEN
  1076.                 dummyView:=theSubView.FirstSubViewThat (TestSubView);
  1077.         END;
  1078.     TestSubView:=foundView <> NIL;
  1079.     END;
  1080.     
  1081. BEGIN
  1082.     foundView:=NIL;
  1083.     ItemCount:=0;
  1084.     IF Window.IsShown THEN
  1085.         dummyView:=Window.FirstSubViewThat (TestSubView);
  1086.     RankToItem:=foundView;
  1087. END;
  1088.  
  1089.  
  1090. { Report the number of items in a TGridView.  This is here so it can
  1091. be easily overridden if you only want rows or columns to show up as
  1092. seperate user interface items, instead of each cell. }
  1093. FUNCTION TVUAssist.CountGridItems (theGridView: TGridView): integer;
  1094. BEGIN
  1095.     CountGridItems:=theGridView.fNumOfRows*theGridView.fNumOfCols;
  1096. END;
  1097.  
  1098.  
  1099.  
  1100. {Given a view item and the control/dialog item flag, decide if this
  1101. view object is a control if the flag=ControlsOnly, or if its a dialog
  1102. item if the flag=DialogItems, or if its neither.  Of course, MacApp 
  1103. doesn't have a concept of dialog items, so we improvise.  Here are the criteria.
  1104. Any descendent of TCtlMgr is a control.  Descendants of TPopup are also classified
  1105. as contols because V.U. can normally only deal with popups which utilize the popup
  1106. CDEF.  So V.U. expects popups to be controls.
  1107.  
  1108. Descendents of TTEView and some descendants of TControl (specifically TEditText, 
  1109. TStaticText, TIcon, TPicture, and TGridView) are considered to be DialogItems for V.U.'s sake.  
  1110. GridViewItems are considered along with other DlogViewItems only if GridViewItems parameter 
  1111. is true.}
  1112. FUNCTION TVUAssist.GetItemType (Item :TView; DlogViewItems :Boolean;
  1113.     GridViewItems: Boolean) :ViewItems;
  1114. BEGIN
  1115.     GetItemType:=VINotMember;
  1116.     IF Member (Item, TPopup) THEN
  1117.         GetItemType:=VIPopup
  1118.     ELSE IF Member (Item, TRadio) THEN
  1119.         GetItemType:=VIRadio
  1120.     ELSE IF Member (Item, TCheckBox) THEN
  1121.         GetItemType:=VICheckBox
  1122.     ELSE IF Member (Item, TScrollBar) THEN
  1123.         GetItemType:=VIScrollBar
  1124.     ELSE IF Member (Item, TButton) THEN    
  1125.         GetItemType:=VIButton;            
  1126.     IF DlogViewItems THEN                
  1127.     BEGIN
  1128.         IF Member (Item, TEditText) THEN    {TEditText descends from TStaticText}
  1129.             GetItemType:=VIEditText
  1130.         ELSE IF Member (Item, TStaticText) THEN
  1131.             GetItemType:=VIStatText
  1132.         ELSE IF Member (Item, TIcon) THEN
  1133.             GetItemType:=VIIcon
  1134.         ELSE IF Member (Item, TPicture) THEN
  1135.             GetItemType:=VIPicture
  1136.         ELSE IF Member (Item, TTEView) AND NOT Member (Item, TDialogTEView) THEN
  1137.             GetItemType:=VITextEdit;
  1138.         IF (fGridItemSupport AND GridViewItems) THEN
  1139.         BEGIN 
  1140.             IF Member (Item, TGridView) THEN 
  1141.             BEGIN                                                     
  1142.                 GetItemType:=VIGridItem;
  1143.             END;
  1144.         END;
  1145.     END;
  1146.     
  1147. END;
  1148.  
  1149.  
  1150.  
  1151. {========================================== TGridItem ================================}
  1152.  
  1153. {$S VUAssistSeg}
  1154.  
  1155. { Instantiate a TGridItem object, and fill in its fields..  This is here 
  1156. so it can be overridden if you only want rows or columns to show 
  1157. up as seperate user interface items, instead of each individual cells. }
  1158. PROCEDURE TGridItem.IGridItem (theGridView: TGridView; Rank: integer);
  1159. BEGIN
  1160.     SELF.fGridView:=theGridView;
  1161.     SELF.fRank:=Rank;
  1162.     SELF.fRow:=(Rank-1) DIV theGridView.fNumOfCols +1;
  1163.     SELF.fColumn:=(Rank-1) MOD theGridView.fNumOfCols +1;
  1164. END;
  1165.  
  1166. { Provide the bounding rect of a griditem }
  1167. PROCEDURE TGridItem.GetExtent (VAR itsExtent: VRect);
  1168. VAR
  1169.     aCell: GridCell;
  1170. BEGIN
  1171.     aCell.v:=fRow;
  1172.     aCell.h:=fColumn;
  1173.     fGridView.CellToVRect (aCell, itsExtent);
  1174. END;
  1175.  
  1176.  
  1177. { call the LocalToWindow method of the GridView associated with the griditem }
  1178. PROCEDURE TGridItem.LocalToWindow(VAR thePoint: VPoint);
  1179. BEGIN
  1180.     fGridView.LocalToWindow(thePoint);
  1181. END;
  1182.  
  1183.